package com.genexususa.eo.connection.google.analytics;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.analytics.Analytics;
import com.google.api.services.analytics.AnalyticsScopes;
import com.google.api.services.analytics.model.Accounts;
import com.google.api.services.analytics.model.GaData;
import com.google.api.services.analytics.model.GaData.ColumnHeaders;
import com.google.api.services.analytics.model.GaData.ProfileInfo;
import com.google.api.services.analytics.model.GaData.Query;
import com.google.api.services.analytics.model.Profiles;
import com.google.api.services.analytics.model.Webproperties;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: Emiliano Martinez
 * Date: 3/7/13
 * Time: 2:57 PM
 * To change this template use File | Settings | File Templates.
 */
public class Main {

    /**
     * Be sure to specify the name of your application. If the application name is {@code null} or
     * blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0".
     */
    private static final String APPLICATION_NAME = "L2TMEDIA";

    /**
     * Used to identify from which reporting profile to retrieve data.
     * Format is ga:xxx where xxx is your profile ID.
     */
    //private static final String TABLE_ID = "ga:69894122";
    private static String TABLE_ID = "ga:69894122";

    /** Global instance of the HTTP transport. */
    private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();

    /** Global instance of the JSON factory. */
    private static final JsonFactory JSON_FACTORY = new JacksonFactory();


    private static FileDataStoreFactory DATA_STORE_FACTORY;

    public static void main(String[] args) {
        try {

            /*
            Analytics analytics = initializeAnalytics();


            String profileId = getProfileId(analytics);
            TABLE_ID = String.format("ga:%s",profileId);

            System.out.println("ProfileId: " + profileId);
            System.out.println("TableId: " + TABLE_ID);
            System.out.println();

            GaData gaData = executeDataQuery(analytics, TABLE_ID);

            printReportInfo(gaData);
            System.out.println();
            printProfileInfo(gaData);
            System.out.println();
            printQueryInfo(gaData);
            System.out.println();
            printPaginationInfo(gaData);
            System.out.println();
            printTotalsForAllResults(gaData);
            System.out.println();
            printColumnHeaders(gaData);
            System.out.println();
            printDataTable(gaData);
            System.out.println();
            */

            String xml;


            // total organic visits
            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\"> " +
                    "<filePath>C:\\L2T\\Import\\Analytics\\ov</filePath>" +
                    "<applicationName>L2TMEDIA</applicationName>" +
                    "<profileId>69894122</profileId>" +
                    "<startDate>2013-07-01</startDate> " +
                    "<endDate>2013-07-31</endDate> " +
                    "<metrics> <Item>ga:visits</Item> </metrics> " +
                    "<filters> <Item>ga:medium==organic</Item> </filters> " +
                    "<maxResults>0</maxResults> " +
                    "</GoogleAnalyticsQuery>";

            // non branded organic visits
            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\"> " +
                    "<filePath>C:\\L2T\\Import\\Analytics\\nbov</filePath>" +
                    "<applicationName>L2TMEDIA</applicationName>" +
                    "<profileId>69894122</profileId>" +
                    "<startDate>2013-07-01</startDate> " +
                    "<endDate>2013-07-31</endDate> " +
                    "<metrics> <Item>ga:visits</Item> </metrics> " +
                    "<dimensions> <Item>ga:keyword</Item> </dimensions>" +
                    " <filters> <Item>ga:medium==organic</Item> <Item>ga:keyword!=(not provided)</Item> <Item>ga:keyword!=GeneXusUSA</Item> </filters> " +
                    "<maxResults>0</maxResults>" +
                    "</GoogleAnalyticsQuery>";

            // organic page views
            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\"> " +
                    "<filePath>C:\\L2T\\Import\\Analytics\\opv_69894122.xml</filePath>" +
                    "<applicationName>L2TMEDIA</applicationName>" +
                    "<profileId>69894122</profileId>" +
                    "<startDate>2013-07-01</startDate> " +
                    "<endDate>2013-07-31</endDate> " +
                    "<metrics> <Item>ga:pageviews</Item> </metrics> " +
                    "<filters> <Item>ga:medium==organic</Item> </filters> " +
                    "<maxResults>0</maxResults> " +
                    "</GoogleAnalyticsQuery>";


            // bounce rate
            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\"> " +
                    "<filePath>C:\\L2T\\Import\\Analytics\\br_69894122.xml</filePath>" +
                    "<applicationName>L2TMEDIA</applicationName>" +
                    "<profileId>69894122</profileId>" +
                    "<startDate>2013-07-01</startDate> " +
                    "<endDate>2013-07-31</endDate> " +
                    "<metrics> <Item>ga:entranceBounceRate</Item> <Item>ga:visitBounceRate</Item> </metrics> " +
                    "<maxResults>0</maxResults> " +
                    "</GoogleAnalyticsQuery>";

            // average time on site
            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\"> " +
                    "<filePath>C:\\L2T\\Import\\Analytics\\avg</filePath>" +
                    "<applicationName>L2TMEDIA</applicationName>" +
                    "<profileId>69894122</profileId>" +
                    "<startDate>2013-07-01</startDate> " +
                    "<endDate>2013-07-31</endDate> " +
                    "<metrics> <Item>ga:avgTimeOnSite</Item> </metrics> " +
                    "<maxResults>0</maxResults> " +
                    "</GoogleAnalyticsQuery>";

            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\">\n" +
                    "\t<filePath>C:\\L2T\\Import\\Analytics\\nbov</filePath>\n" +
                    "\t<applicationName>L2TMEDIA</applicationName>\n" +
                    "\t<profileId>69894122</profileId>\n" +
                    "\t<startDate>2013-07-01</startDate>\n" +
                    "\t<endDate>2013-07-31</endDate>\n" +
                    "\t<metrics>\n" +
                    "\t\t<Item>ga:visits</Item>\n" +
                    "\t</metrics>\n" +
                    "\t<dimensions>\n" +
                    "\t\t<Item>ga:keyword</Item>\n" +
                    "\t</dimensions>\n" +
                    "\t<filters>\n" +
                    "\t\t<Item>ga:medium==organic</Item>\n" +
                    "\t\t<Item>ga:keyword!=(not provided)</Item>\n" +
                    "\t\t<Item>ga:keyword!=GeneXusUSA</Item>\n" +
                    "\t</filters>\n" +
                    "\t<maxResults>0</maxResults>\n" +
                    "</GoogleAnalyticsQuery>";



            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\">\n" +
                    "\t<filePath>C:\\L2T\\nbov</filePath>\n" +
                    "\t<applicationName>L2TMEDIA</applicationName>\n" +
                    "\t<profileId>69611940</profileId>\n" +
                    "\t<startDate>2014-01-01</startDate>\n" +
                    "\t<endDate>2014-06-30</endDate>\n" +
                    "\t<metrics>\n" +
                    "\t\t<Item>ga:visits</Item>\n" +
                    "\t</metrics>\n" +
                    "\t<dimensions>\n" +
                    "\t\t<Item>ga:keyword</Item>\n" +
                    "\t</dimensions>\n" +
                    "\t<filters>\n" +
                    "\t\t<Item>ga:medium==organic</Item>\n" +
                    "\t\t<Item>ga:keyword!=(not provided)</Item>\n" +
                    "\t\t<Item>ga:keyword!=GeneXusUSA</Item>\n" +
                    "\t</filters>\n" +
                    "\t<maxResults>0</maxResults>\n" +
                    "</GoogleAnalyticsQuery>";

            xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\">\n" +
                    "\t<filePath>C:\\L2T\\nbov</filePath>\n" +
                    "\t<applicationName>L2TMEDIA</applicationName>\n" +
                    "\t<profileId>65425896</profileId>\n" +
                    "\t<startDate>2014-07-06</startDate>\n" +
                    "\t<endDate>2014-08-05</endDate>\n" +
                    "\t<metrics>\n" +
                    "\t\t<Item>ga:goal6Completions</Item>\n" +
                    "\t</metrics>\n" +
                    "\t<dimensions>\n" +
                    "\t\t<Item>ga:adwordsCampaignID</Item>\n" +
                    "\t</dimensions>\n" +
                    //"\t<filters>\n" +
                    //"\t</filters>\n" +
                    "\t<maxResults>0</maxResults>\n" +
                    "</GoogleAnalyticsQuery>";

            /*xml = "<GoogleAnalyticsQuery xmlns=\"L2TMedia1.5\">\n" +
                    "\t<filePath>C:\\L2T\\nbov</filePath>\n" +
                    "\t<applicationName>L2TMEDIA</applicationName>\n" +
                    "\t<profileId>65425896</profileId>\n" +
                    "\t<startDate>2014-01-01</startDate>\n" +
                    "\t<endDate>2014-06-30</endDate>\n" +
                    "\t<dimensions>\n" +
                    "\t\t<Item>mcf:conversionType</Item>\n" +
                    "\t</dimensions>\n" +
                    "\t<metrics>\n" +
                    "\t\t<Item>mcf:totalConversions</Item>\n" +
                    "\t</metrics>\n" +
                    "\t<maxResults>0</maxResults>\n" +
                    "</GoogleAnalyticsQuery>";  */

            //AnalyticsManager am = new AnalyticsManager();
            //am.executeQuery(xml);
            //am.getInventoryPageViews(xml);
            //am.getTop10Keywords(xml);
            //am.getConversionGoalNumber(xml);

            //Process p = Runtime.getRuntime().exec("cmd /c cd c:\\analytics & java -cp *;analytics.jar;. com.genexususa.eo.google.main.getTop10Keywords 1");
            /*InputStream in = p.getInputStream();
            int ch;
            while((ch = in.read()) != -1) {
                System.out.print((char)ch);
            }  */

        }catch (Exception e){
            e.printStackTrace();

        } catch (Throwable t) {
            t.printStackTrace();
        }
    }




    private static Analytics initializeAnalytics() throws Exception  {
        // Authorization.
        Credential credential = authorize();

        // Set up and return Google Analytics API client.
        return new Analytics.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME)
                .build();
    }

    private static String getProfileId(Analytics analytics) throws IOException{
        String profileId = null;
        Accounts accounts = analytics.management().accounts().list().execute();
        if (accounts.getItems().isEmpty()){
            System.err.println("No accounts were found");
        }else{
            String firstAccountId = accounts.getItems().get(0).getId();

            Webproperties webproperties = analytics.management().webproperties()
                    .list(firstAccountId).execute();
            if(webproperties.getItems().isEmpty()){
                System.err.println("No webproperties were found");
            }else{
                String firstWebPropertyId = webproperties.getItems().get(0).getId();
                Profiles profiles = analytics.management().profiles().list(firstAccountId, firstWebPropertyId).execute();
                if (profiles.getItems().isEmpty()){
                    System.err.println("No profiles were found");
                }else{
                    profileId = profiles.getItems().get(0).getId();
                }
            }
        }
        return profileId;
    }

    /**
     * Returns the top 25 organic search keywords and traffic sources by visits. The
     * Core Reporting API is used to retrieve this data.
     *
     * @param analytics the Analytics service object used to access the API.
     * @param tableId the table ID from which to retrieve data.
     * @return the response from the API.
     * @throws java.io.IOException if an API error occured.
     */
    private static GaData executeDataQuery(Analytics analytics, String tableId) throws IOException {
        /*return analytics.data().ga()
                .get(tableId,                  // Table Id.
                        "2013-02-01",              // Start date.
                        "2013-07-17",              // End date.
                        "ga:visits")               // Metrics.
                .setDimensions("ga:source,ga:keyword")
                .setSort("-ga:visits,ga:source")
                //.setFilters("ga:medium==organic")
                .setMaxResults(25)
                .execute();
                */
        return analytics.data().ga()
                .get(tableId,                  // Table Id.
                        "2013-02-01",              // Start date.
                        "2013-07-17",              // End date.
                        "ga:visits")               // Metrics.
                .setDimensions("ga:source, ga:keyword, ga:browser, ga:city")
                .setSort("-ga:visits, ga:source, ga:browser, ga:city")
                        //.setFilters("ga:medium==organic")
                .setMaxResults(25)
                .execute();
    }


    /** Authorizes the installed application to access user's protected data. */
    private static Credential authorize() throws Exception {

        // load client secrets
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
                JSON_FACTORY, new InputStreamReader(
                AnalyticsConnector.class.getResourceAsStream("/client_secrets.json")));
        if (clientSecrets.getDetails().getClientId().startsWith("Enter")
                || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
            System.out.println(
                    "Enter Client ID and Secret from https://code.google.com/apis/console/?api=analytics "
                            + "into analytics-cmdline-sample/src/main/resources/client_secrets.json");
            System.exit(1);
        }
        // set up authorization code flow
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
                HTTP_TRANSPORT, JSON_FACTORY, clientSecrets,
                Collections.singleton(AnalyticsScopes.ANALYTICS_READONLY)).setDataStoreFactory(
                DATA_STORE_FACTORY).build();
        // authorize
        return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
    }

    private static void printProfileInfo(GaData gaData) {
        ProfileInfo profileInfo = gaData.getProfileInfo();

        System.out.println("Profile Info");
        System.out.println("Account ID: " + profileInfo.getAccountId());
        System.out.println("Web Property ID: " + profileInfo.getWebPropertyId());
        System.out.println("Internal Web Property ID: " + profileInfo.getInternalWebPropertyId());
        System.out.println("Profile ID: " + profileInfo.getProfileId());
        System.out.println("Profile Name: " + profileInfo.getProfileName());
        System.out.println("Table ID: " + profileInfo.getTableId());
    }

    private static void printReportInfo(GaData gaData) {
        System.out.println();
        System.out.println("Response:");
        System.out.println("ID:" + gaData.getId());
        System.out.println("Self link: " + gaData.getSelfLink());
        System.out.println("Kind: " + gaData.getKind());
        System.out.println("Contains Sampled Data: " + gaData.getContainsSampledData());
    }

    private static void printQueryInfo(GaData gaData) {
        Query query = gaData.getQuery();

        System.out.println("Query Info:");
        System.out.println("Ids: " + query.getIds());
        System.out.println("Start Date: " + query.getStartDate());
        System.out.println("End Date: " + query.getEndDate());
        System.out.println("Metrics: " + query.getMetrics()); // List
        System.out.println("Dimensions: " + query.getDimensions()); // List
        System.out.println("Sort: " + query.getSort()); // List
        System.out.println("Segment: " + query.getSegment());
        System.out.println("Filters: " + query.getFilters());
        System.out.println("Start Index: " + query.getStartIndex());
        System.out.println("Max Results: " + query.getMaxResults());
    }

    /**
     * Prints common pagination information.
     *
     * @param gaData the data returned from the API.
     */
    private static void printPaginationInfo(GaData gaData) {
        System.out.println("Pagination Info:");
        System.out.println("Previous Link: " + gaData.getPreviousLink());
        System.out.println("Next Link: " + gaData.getNextLink());
        System.out.println("Items Per Page: " + gaData.getItemsPerPage());
        System.out.println("Total Results: " + gaData.getTotalResults());
    }

    /**
     * Prints the total metric value for all rows the query matched.
     *
     * @param gaData the data returned from the API.
     */
    private static void printTotalsForAllResults(GaData gaData) {
        System.out.println("Metric totals over all results:");
        Map<String, String> totalsMap = gaData.getTotalsForAllResults();
        for (Map.Entry<String, String> entry : totalsMap.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }

    /**
     * Prints the information for each column.
     * The reporting data from the API is returned as rows of data. The column
     * headers describe the names and types of each column in rows.
     *
     * @param gaData the data returned from the API.
     */
    private static void printColumnHeaders(GaData gaData) {
        System.out.println("Column Headers:");

        for (ColumnHeaders header : gaData.getColumnHeaders()) {
            System.out.println("Column Name: " + header.getName());
            System.out.println("Column Type: " + header.getColumnType());
            System.out.println("Column Data Type: " + header.getDataType());
        }
    }

    /**
     * Prints all the rows of data returned by the API.
     *
     * @param gaData the data returned from the API.
     */
    private static void printDataTable(GaData gaData) {
        if (gaData.getTotalResults() > 0) {
            System.out.println("Data Table:");

            // Print the column names.
            for (ColumnHeaders header : gaData.getColumnHeaders()) {
                System.out.format("%-32s", header.getName());
            }
            System.out.println();

            // Print the rows of data.
            for (List<String> rowValues : gaData.getRows()) {
                for (String value : rowValues) {
                    System.out.format("%-32s", value);
                }
                System.out.println();
            }
        } else {
            System.out.println("No data");
        }
    }


}
